Python之OpenGL笔记(17):键盘鼠标控制摄像机移动旋转

您所在的位置:网站首页 python 摄像机 Python之OpenGL笔记(17):键盘鼠标控制摄像机移动旋转

Python之OpenGL笔记(17):键盘鼠标控制摄像机移动旋转

2024-01-22 00:32| 来源: 网络整理| 查看: 265

一、目的

1、键盘控制摄像机自由移动; 2、鼠标控制摄像机旋转; 3、鼠标滚轮放大缩小视野。

二、程序运行结果

在这里插入图片描述

三、自由移动

view = lookAt(cameraPos, cameraPos + cameraFront, cameraUp) cameraPos为摄像机位置 cameraPos + cameraFront为物体位置   当我们按下WASD键,摄像机的位置都会相应更新。如果我们希望向前或向后移动,我们就把位置向量加上或减去方向向量。如果我们希望向旁边移动,我们做一个叉乘来创建一个右向量,沿着它移动就可以了。这样就创建了类似使用摄像机横向、前后移动的效果。   注意,我们对右向量进行了标准化。如果我们没对这个向量进行标准化,最后的叉乘结果会根据cameraFront变量的大小返回不同的大小。如果我们不对向量进行标准化,我们就得根据摄像机的方位加速或减速移动了,但假如进行了标准化移动就是匀速的。   一个技巧是只在回调函数中跟踪哪个键被按下/释放。在游戏循环中我们读取这些值,检查那个按键被激活了,然后做出相应反应。我们只储存哪个键被按下/释放的状态信息,在游戏循环中对状态做出反应,我们来创建一个布尔数组代表按下/释放的键:

四、视角移动

  欧拉角(Euler Angle)是表示3D空间中可以表示任何旋转的三个值,由莱昂哈德·欧拉在18世纪提出。有三种欧拉角:俯仰角(Pitch)、偏航角(Yaw)和滚转角(Roll),   俯仰角是描述我们如何往上和往下看的角(X轴,Pitch)。   偏航角表示我们往左和往右看的大小(Y轴,Yaw)。   滚转角代表我们如何翻滚摄像机(Z轴,Roll)。   用一个给定的俯仰角和偏航角,我们可以把它们转换为一个代表新的方向向量的3D向量。   front.x = cos(glm::radians(pitch)) * cos(glm::radians(yaw))   // 注意我们先把角度转为弧度,direction代表摄像机的前轴

五、鼠标输入

  偏航角和俯仰角是从鼠标移动获得的,鼠标水平移动影响偏航角,鼠标垂直移动影响俯仰角。它的思想是储存上一帧鼠标的位置,在当前帧中我们当前计算鼠标位置和上一帧的位置相差多少。如果差别越大那么俯仰角或偏航角就改变越大。   在处理FPS风格的摄像机鼠标输入的时候,我们必须在获取最终的方向向量之前做下面这几步: 1、计算鼠标和上一帧的偏移量。 2、把偏移量添加到摄像机和俯仰角和偏航角中。 3、对偏航角和俯仰角进行最大和最小值的限制。 4、计算方向向量。

六、缩放

  我们还要往摄像机系统里加点东西,实现一个缩放接口。前面教程中我们说视野(Field of View或fov)定义了我们可以看到场景中多大的范围。当视野变小时可视区域就会减小,产生放大了的感觉。我们用鼠标滚轮来放大。和鼠标移动、键盘输入一样我们需要一个鼠标滚轮的回调函数。 void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)   yoffset值代表我们滚动的大小。当scroll_callback函数调用后,我们改变全局aspect变量的内容。因为45.0f是默认的fov,我们将会把缩放级别限制在1.0f到45.0f。   我们现在在每一帧都必须把透视投影矩阵上传到GPU,但这一次使aspect变量作为它的fov: projection = glm::perspective(aspect, (GLfloat)WIDTH/(GLfloat)HEIGHT, 0.1f, 100.0f);

七、源代码 """ glfw_cube06.py Author: dalong10 Description: Draw 4 Cube, learning OPENGL """ import glutils #Common OpenGL utilities,see glutils.py import sys, random, math import OpenGL from OpenGL.GL import * from OpenGL.GL.shaders import * import numpy import numpy as np import glfw strVS = """ #version 330 core layout(location = 0) in vec3 position; layout (location = 1) in vec2 inTexcoord; out vec2 outTexcoord; uniform mat4 uMVMatrix; uniform mat4 uPMatrix; uniform float a; uniform float b; uniform float c; uniform float scale; uniform float theta; void main(){ mat4 rot1=mat4(vec4(1.0, 0.0,0.0,0), vec4(0.0, 1.0,0.0,0), vec4(0.0,0.0,1.0,0.0), vec4(a,b,c,1.0)); mat4 rot2=mat4(vec4(scale, 0.0,0.0,0.0), vec4(0.0, scale,0.0,0.0), vec4(0.0,0.0,scale,0.0), vec4(0.0,0.0,0.0,1.0)); mat4 rot3=mat4( vec4(0.5+0.5*cos(theta), 0.5-0.5*cos(theta), -0.707106781*sin(theta), 0), vec4(0.5-0.5*cos(theta),0.5+0.5*cos(theta), 0.707106781*sin(theta),0), vec4(0.707106781*sin(theta), -0.707106781*sin(theta),cos(theta), 0.0), vec4(0.0, 0.0,0.0, 1.0)); gl_Position=uPMatrix * uMVMatrix * rot2 *rot1 *rot3 * vec4(position.x, position.y, position.z, 1.0); outTexcoord = inTexcoord; } """ strFS = """ #version 330 core out vec4 FragColor; in vec2 outTexcoord; uniform sampler2D texture1; void main(){ FragColor = texture(texture1, outTexcoord); } """ class FirstCube: def __init__(self, side): self.side = side # load shaders self.program = glutils.loadShaders(strVS, strFS) glUseProgram(self.program) # attributes self.vertIndex = glGetAttribLocation(self.program, b"position") self.texIndex = glGetAttribLocation(self.program, b"inTexcoord") s = side/2.0 cube_vertices = [ -s, -s, -s, s, -s, -s, s, s, -s, s, s, -s, -s, s, -s, -s, -s, -s, -s, -s, s, s, -s, s, s, s, s, s, s, s, -s, s, s, -s, -s, s, -s, s, s, -s, s, -s, -s, -s, -s, -s, -s, -s, -s, -s, s, -s, s, s, s, s, s, s, s, -s, s, -s, -s, s, -s, -s, s, -s, s, s, s, s, -s, -s, -s, s, -s, -s, s, -s, s, s, -s, s, -s, -s, s, -s, -s, -s, -s, s, -s, s, s,-s, s, s, s, s, s, s, -s, s, s, -s, s,-s ] # texture coords t=1.0 quadT = [ 0,0, t,0, t,t, t,t, 0,t, 0,0, 0,0, t,0, t,t, t,t, 0,t, 0,0, t,0, t,t, 0,t, 0,t, 0,0, t,0, t,0, t,t, 0,t, 0,t, 0,0, t,0, 0,t, t,t, t,0, t,0, 0,0, 0,t, 0,t, t,t, t,0, t,0, 0,0, 0,t ] # set up vertex array object (VAO) self.vao = glGenVertexArrays(1) glBindVertexArray(self.vao) # set up VBOs vertexData = numpy.array(cube_vertices, numpy.float32) self.vertexBuffer = glGenBuffers(1) glBindBuffer(GL_ARRAY_BUFFER, self.vertexBuffer) glBufferData(GL_ARRAY_BUFFER, 4*len(vertexData), vertexData, GL_STATIC_DRAW) tcData = numpy.array(quadT, numpy.float32) self.tcBuffer = glGenBuffers(1) glBindBuffer(GL_ARRAY_BUFFER, self.tcBuffer) glBufferData(GL_ARRAY_BUFFER, 4*len(tcData), tcData,GL_STATIC_DRAW) # enable arrays glEnableVertexAttribArray(self.vertIndex) glEnableVertexAttribArray(self.texIndex) # Position attribute glBindBuffer(GL_ARRAY_BUFFER, self.vertexBuffer) glVertexAttribPointer(self.vertIndex, 3, GL_FLOAT, GL_FALSE, 0,None) # TexCoord attribute glBindBuffer(GL_ARRAY_BUFFER, self.tcBuffer) glVertexAttribPointer(self.texIndex, 2, GL_FLOAT, GL_FALSE, 0,None) # unbind VAO glBindVertexArray(0) glBindBuffer(GL_ARRAY_BUFFER, 0) def render(self,pMatrix,mvMatrix,texid,a,b,c,scale,r): self.texid = texid # enable texture glActiveTexture(GL_TEXTURE0) glBindTexture(GL_TEXTURE_2D, self.texid) # use shader # set proj matrix glUniformMatrix4fv(glGetUniformLocation(self.program, 'uPMatrix'), 1, GL_FALSE, pMatrix) # set modelview matrix glUniformMatrix4fv(glGetUniformLocation(self.program, 'uMVMatrix'), 1, GL_FALSE, mvMatrix) glUseProgram(self.program) glUniform1f(glGetUniformLocation(self.program, "a"), a) glUniform1f(glGetUniformLocation(self.program, "b"), b) glUniform1f(glGetUniformLocation(self.program, "c"), c) glUniform1f(glGetUniformLocation(self.program, "scale"), scale) theta = r*PI/180.0 glUniform1f(glGetUniformLocation(self.program, "theta"), theta) # bind VAO glBindVertexArray(self.vao) glEnable(GL_DEPTH_TEST) # draw glDrawArrays(GL_TRIANGLES, 0, 36) # unbind VAO glBindVertexArray(0) #Is called whenever a key is pressed/released via GLFW def on_key(window, key, scancode, action, mods): if key == glfw.KEY_ESCAPE and action == glfw.PRESS: glfw.set_window_should_close(window,1) elif key >0 and key 89.0): pitch = 89.0 if(pitch < -89.0): pitch = -89.0 cameraFront=[math.cos(math.radians(yaw)) * math.cos(math.radians(pitch)), math.sin(math.radians(pitch)), math.sin(math.radians(yaw))* math.cos(math.radians(pitch)) ] norm = numpy.linalg.norm(cameraFront) cameraFront /= norm def scroll_callback(window, xoffset, yoffset): global aspect if(aspect >= 1.0 and aspect


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3